#include "File.h"

#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sstream>
#ifdef WIN32
#include <io.h>
#include <windows.h>
#include <direct.h>
#endif
#ifdef linux
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>
#endif

#include "strchange.h"
#include "strTrim.h"
#include "pfunc_print.h"

bool pyfree::writeToFile(const char *ptr,const std::string& path, const std::string& mode)
{
	FILE *m_fil = NULL;
	#ifdef WIN32
	if(0==::fopen_s(&m_fil,path.c_str(),mode.c_str()))
	#else
	m_fil = fopen(path.c_str(),mode.c_str());
	if(NULL!=m_fil)
	#endif
	{
		size_t size = 0;
		size = ::fwrite(ptr, static_cast<int>(sizeof(char)), strlen(ptr),m_fil);
		::fclose(m_fil);
		m_fil = NULL;
		if(size>0)
		{
			return true;
		}else{
			return false;
		}
	}
	else{
		m_fil = NULL;
		return false;
	}
}

bool pyfree::writeListInfo(std::vector<std::string> list,const std::string path)
{
	size_t newSize = 0;
	FILE *new_m_fil=NULL;
	#ifdef WIN32
	if(0==::fopen_s(&new_m_fil,path.c_str(),"a+"))
	#else
	new_m_fil = fopen(path.c_str(),"a+");
	if(NULL!=new_m_fil)
	#endif
	{
		for(size_t i=0,lSize=list.size(); i<lSize; i++)
		{
			newSize += ::fwrite(list.at(i).c_str(), static_cast<int>(sizeof(char)), strlen(list.at(i).c_str()),new_m_fil);
		}
		::fclose(new_m_fil);
	}
	new_m_fil = NULL;
	if(newSize>0){
		return true;
	}

	return false;
}

bool pyfree::readFromFile(char *ptr, int &size, int buf_size,const std::string& path, const std::string& mode)
{
	FILE *m_fil=NULL;
	#ifdef WIN32
	if(0==::fopen_s(&m_fil,path.c_str(),mode.c_str()))
	#else
	m_fil = fopen(path.c_str(),mode.c_str());
	if(NULL!=m_fil)
	#endif
	{
		size = static_cast<int>( ::fread(ptr, static_cast<int>(sizeof(char)), (size_t)buf_size,m_fil) );
		::fclose(m_fil);
		m_fil = NULL;
		if(size>0)
		{
			return true;
		}else
			return false;
	}else{
		m_fil = NULL;
		return false;
	}
}

//读取文件每一行得字符串，如果行中存在空格，划分该行字符串，并装在到容器中
bool pyfree::readListInfo(std::vector<std::vector<std::string> > &list,const std::string path,int codef)
{
	FILE *m_fil=NULL;
	#ifdef WIN32
	if(0==::fopen_s(&m_fil,path.c_str(),"r"))
	#else
	m_fil = fopen(path.c_str(),"r");
	if(NULL!=m_fil)
	#endif
	{
		char buf[1024] ={0};
		while(NULL!=::fgets(buf,1024,m_fil))
		{
			std::string _lineInfo = buf;
			trimEnd(_lineInfo);
			#ifdef __linux__
			switch (codef)
			{
				case 1:
				{
					char buff[1024]={0};
					g2u(buf,strlen(buf),buff,1024);
					_lineInfo = buff;
				}
					break;
				case 2:
				{
					char buff[1024]={0};
					a2u(buf,strlen(buf),buff,1024);
					_lineInfo = buff;
				}
					break;
				default:
					break;
			}
			#endif
			std::string buffer;// Have a buffer string
			std::stringstream _lineStr(_lineInfo);// Insert the string into a stream
			std::vector<std::string> _lineList;// Create vector to hold our words
			while(_lineStr >> buffer)
			{
				_lineList.push_back(buffer);
			}
			list.push_back(_lineList);
		}
		::fclose(m_fil);
		m_fil = NULL;
		if(list.empty()){
			return false;
		}
	}else{
		#ifdef WIN32
		Print_WARN("con't open %s, %d \n",path.c_str(), ::GetLastError());
		#endif
		#ifdef linux
		Print_WARN("con't open %s, %s \n",path.c_str(),strerror(errno));
		#endif
		m_fil = NULL;
		return false;
	}
	return true;
}

//将采用","间隔的字符串划分成子字符串集
void pyfree::getNumberFromStr(std::vector<std::string> &ids, std::string idsStr)
{
	if(""==idsStr||"NULL"==idsStr)
		return;
	std::string id = "";
	for(unsigned int i=0,idSize= static_cast<unsigned int>(idsStr.size()); i<idSize; i++)
	{
		if(','==idsStr[i])
		{//use str ',' to dirve the idsStr;
			if(""!=id)
			{
				ids.push_back(id);
				id.clear();
				id = "";
			}else{
				ids.push_back(id);
			}
		}else if(i==(idSize-1))
		{
			if(""!=id)
			{
				ids.push_back(id);
				id.clear();
				id = "";
			}
		}else{
			id.push_back(idsStr[i]);
		}
	}
}

//读取文件每一行得字符串，如果行中存在","，划分该行字符串，并装在到容器中
bool pyfree::readListInfo_dot(std::vector<std::vector<std::string> > &list,const std::string path,int codef)
{
	FILE *m_fil=NULL;
	#ifdef WIN32
	if(0==::fopen_s(&m_fil,path.c_str(),"r"))
	#else
	m_fil = fopen(path.c_str(),"r");
	if(NULL!=m_fil)
	#endif
	{
		char buf[1024] ={0};
		std::string _lineInfo = "";
		while(NULL!=::fgets(buf,1024,m_fil))
		{
			_lineInfo = buf;
			trim(_lineInfo);
			#ifdef __linux__
			switch (codef)
			{
				case 1:
				{
					char buff[1024]={0};
					g2u(buf,strlen(buf),buff,1024);
					_lineInfo = buff;
				}
					break;
				case 2:
				{
					char buff[1024]={0};
					a2u(buf,strlen(buf),buff,1024);
					_lineInfo = buff;
				}
					break;
				default:
					break;
			}
			#endif
			std::vector<std::string> _lineList;
			getNumberFromStr(_lineList,_lineInfo);
			list.push_back(_lineList);
		}
		::fclose(m_fil);
		m_fil = NULL;
		if(list.empty()){
			return false;
		}
	}else{
		#ifdef WIN32
		Print_WARN("con't open %s, %d \n",path.c_str(), ::GetLastError());
		#endif
		#ifdef linux
		Print_WARN("con't open %s, %s \n",path.c_str(),strerror(errno));
		#endif
		m_fil = NULL;
		return false;
	}
	return true;
}

//读取文件，并将每一行字符串载入容器
bool pyfree::readListInfo(std::vector<std::string> &list,const std::string path,int codef)
{
	FILE *m_fil=NULL;
	#ifdef WIN32
	if(0==::fopen_s(&m_fil,path.c_str(),"r"))
	#else
	m_fil = fopen(path.c_str(),"r");
	if(NULL!=m_fil)
	#endif
	{
		char buf[512] ={0};
		std::string _lineInfo="";
		while(NULL!=::fgets(buf,512,m_fil))
		{
			_lineInfo = buf;
			trimEnd(_lineInfo);
			#ifdef __linux__
			switch (codef)
			{
				case 1:
				{
					char buff[1024]={0};
					g2u(buf,strlen(buf),buff,1024);
					_lineInfo = buff;
				}
					break;
				case 2:
				{
					char buff[1024]={0};
					a2u(buf,strlen(buf),buff,1024);
					_lineInfo = buff;
				}
					break;
				default:
					break;
			}
			#endif
			list.push_back(_lineInfo);
		}
		::fclose(m_fil);
		m_fil = NULL;
		if(list.empty()){
			return false;
		}
	}else{
		#ifdef WIN32
		Print_WARN("con't open %s, %d \n",path.c_str(), ::GetLastError());
		#endif
		#ifdef linux
		Print_WARN("con't open %s, %s \n",path.c_str(),strerror(errno));
		#endif
		m_fil = NULL;
		return false;
	}
	return true;
}

//获得dire目录下扩展名为extName的所有文件名
void pyfree::getAllFileName_dot(const std::string& directory, const std::string& extName, std::vector<std::string>& fileNames)
{
	getAllFileNamePrivate(directory,extName,fileNames,true);
}

//获得dire目录下扩展名为extName的所有文件名
void pyfree::getAllFileName(const std::string& directory, const std::string& extName, std::vector<std::string>& fileNames)
{
	getAllFileNamePrivate(directory,extName,fileNames);
}

void pyfree::getAllFileNamePrivate(const std::string& directory, const std::string& extName, std::vector<std::string>& fileNames,bool f)
{
	#ifdef WIN32
	_finddata_t fileInfo;
	intptr_t hFile;
	std::string filter = directory;
	char bch = static_cast<char>(('//') & 0X00FF);
	if(filter[filter.size()-1] != bch)
	{
		filter.push_back(bch);
	}
	filter += "*.";
	filter += extName;
	hFile = _findfirst(filter.c_str(),&fileInfo);
	if(hFile == -1)
	{
		return;
	}
	do {
		if (extName.empty())
		{
			if ((fileInfo.attrib & _A_SUBDIR))
			{
				if (0==strcmp(fileInfo.name,".") || 0==strcmp(fileInfo.name,"..") )
				{
					continue;
				}
				fileNames.push_back(fileInfo.name);
			}
		}else{
			std::string name(fileInfo.name);
			if(f){
				fileNames.push_back(name);
			}else{
				fileNames.push_back(name.substr(0,name.find_last_of('.')));
			}
			// fileNames.push_back(name.substr(0,name.find_last_of('.')));
		}
	} while (_findnext(hFile,&fileInfo) == 0);
	_findclose(hFile);
	#endif

	#ifdef linux
	std::string curdir = directory;
	if(curdir[curdir.size()-1] != '/'){
		curdir.push_back('/');
	}
	DIR *dfd;
	if( (dfd = opendir(curdir.c_str())) == NULL )
	{
		Print_WARN("open %s error with msg is: %s\n",curdir.c_str(),strerror(errno));
        return;
	}
	struct dirent    *dp;
	while ((dp = readdir(dfd)) != NULL)
	{
		if (extName.empty()){
			if (dp->d_type == DT_DIR)
			{
				if ( 0==strcmp(dp->d_name, ".") || 0==strcmp(dp->d_name, "..") )
				{
					continue;
				}
				fileNames.push_back(dp->d_name);
			}
		}else{
			if ( NULL==strstr(dp->d_name, extName.c_str()) )
			{
				continue;
			}
			std::string name(dp->d_name);
			if(f)
			{
				fileNames.push_back(name);
			}else{
				fileNames.push_back(name.substr(0,name.find_last_of('.')));
			}
		}
	}
	if (NULL != dp) {
		delete dp;
		dp = NULL;
	}
	if (NULL != dfd) {
		closedir(dfd);
		dfd = NULL;
	}
	#endif
}

unsigned int pyfree::getFileModifyTime(const std::string file_path)
{
	unsigned int ret = 0;
#if defined(WIN32)
	_finddata_t fileInfo;
	intptr_t hFile;
	hFile = _findfirst(file_path.c_str(),&fileInfo);
	if(hFile != -1)
	{
		ret = static_cast<unsigned int>(fileInfo.time_write);
	}else{
		Print_WARN("get file %s last modify error: %d \n"
			,file_path.c_str(), ::GetLastError());
	}
	_findclose(hFile);
#elif defined(linux)
	struct stat el;
	if(0==stat(file_path.c_str(), &el))
	{
		ret =  static_cast<unsigned int>(el.st_mtime);
	}else{
		Print_WARN("get file %s last modify time error: %s\n"
			,file_path.c_str(),strerror(errno));
	}
#else
	ret = 0;
#endif // WIN32
	return ret;
}

void pyfree::renameFile(const std::string& _oldName, const std::string& _newName)
{
	#ifdef WIN32
	_finddata_t fileInfo;
	intptr_t hFile;
	hFile = _findfirst(_oldName.c_str(),&fileInfo);
	if(hFile == -1)
	{
		Print_WARN("can't find file %s \n",_oldName.c_str());
		writeToFile("",_newName,"w");
		return;
	}
	// do {
	// 	std::string name(fileInfo.name);
	// 	fileNames.push_back(name.substr(0,name.find_last_of('.')));
	// } while (_findnext(hFile,&fileInfo) == 0);
	_findclose(hFile);
	#endif
	#ifdef linux
	FILE* m_fil = fopen(_oldName.c_str(),"r");
	if(NULL==m_fil){
		return;
	}
	fclose(m_fil);
	m_fil = NULL;
	#endif

	Print_NOTICE("%s, %s\n", _oldName.c_str(),_newName.c_str());
	int ret = rename(_oldName.c_str(),_newName.c_str());
	if(0 != ret)
	{
		Print_WARN("can't rename %s to %s \n",_oldName.c_str(),_newName.c_str());
		return;
	}
}

void pyfree::removeFile(const std::string& _Name)
{
	int ret = remove(_Name.c_str());
	if(0 != ret)
	{
		Print_WARN("can't remove %s \n",_Name.c_str());
		return;
	}
}

bool pyfree::isExist(std::string file)
{
	#ifdef WIN32
	_finddata_t fileInfo;
	intptr_t hFile = _findfirst(file.c_str(),&fileInfo);
	if(hFile == -1)
	{
		return false;
	}
	_findclose(hFile);

	return true;
	#else
	FILE *m_fil=NULL;
	m_fil=fopen(file.c_str(),"rb");
	if(NULL==m_fil){
		return false;
	}else{
		fclose(m_fil);
		m_fil = NULL;
	}
	return true;
	#endif
}

bool pyfree::isExist(std::string dir,std::string file)
{
	std::string path = dir;
#ifdef WIN32
	path+="\\";
#else
	path+="/";
#endif
	path+=file;
	return isExist(path);
};

void pyfree::divXmlFile(std::string _xmlFile,std::string _xmlDir,std::string _xmlDiv,bool utfFlag)
{
	static int substationIndex = 1;
	FILE *m_fil=NULL;
	FILE *new_m_fil=NULL;

	std::string _xmlNode="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
	_xmlNode = utfFlag?ASCII2UTF_8(_xmlNode):_xmlNode;
	std::string _xmlHead = "<"+_xmlDiv;
	std::string _xmlEnd = "</"+_xmlDiv+">";
#ifdef WIN32
	if(0==::fopen_s(&m_fil,_xmlFile.c_str(),"r"))
#else
	if(NULL!=(m_fil=fopen(_xmlFile.c_str(),"rb")))
#endif
	{
		char buf[512] ={0};
		while(NULL!=::fgets(buf,512,m_fil))
		{
			std::string _lineInfo = buf;
			_lineInfo = utfFlag?ASCII2UTF_8(_lineInfo):_lineInfo;
			std::string::size_type _posH = _lineInfo.find(_xmlHead);
			if(std::string::npos != _posH)
			{
				char newxml[256]={0};
				sprintf(newxml,"%s\\%s_%d.xml",_xmlDir.c_str(),_xmlDiv.c_str(),substationIndex);
				#ifdef WIN32
				if(0==::fopen_s(&new_m_fil,newxml,"a+"))
				{
					::fwrite(_xmlNode.c_str(), static_cast<int>(sizeof(char)), strlen(_xmlNode.c_str()),new_m_fil);
				}
				#else
				if(NULL!=(new_m_fil=fopen(newxml,"a+")))
				{
					int newSize = fwrite(_xmlNode.c_str(), static_cast<int>(sizeof(char)), strlen(_xmlNode.c_str()),new_m_fil);
					if(newSize<=0)
					{
						Print_WARN("newxml=%s,newSize=%d write failed\n",newxml,newSize);
					}
				}else{
					Print_WARN("open %s error\n",newxml);
				}
				#endif
			}
			if(NULL!=new_m_fil){
				#ifdef WIN32
				::fwrite(_lineInfo.c_str(), static_cast<int>(sizeof(char)), strlen(_lineInfo.c_str()),new_m_fil);
				#else
				int lineSize = fwrite(_lineInfo.c_str(), static_cast<int>(sizeof(char)), strlen(_lineInfo.c_str()),new_m_fil);
				if(lineSize<=0){
					Print_WARN("write _lineInfo=%s, lineSize=%d error\n",_lineInfo.c_str(),lineSize);
				}
				#endif
			}
			std::string::size_type  _posE = _lineInfo.find(_xmlEnd);
			if(std::string::npos != _posE)
			{
				if(NULL!=new_m_fil)
				{
					#ifdef WIN32
					::fclose(new_m_fil);
					#else
					fclose(new_m_fil);
					#endif
					new_m_fil=NULL;
					substationIndex+=1;
				}
			}
		}
		#ifdef WIN32
		::fclose(m_fil);
		#else
		fclose(m_fil);
		#endif
		m_fil=NULL;
	}else{
		Print_WARN("con't open %s \n",_xmlFile.c_str());
		m_fil = NULL;
	}
};

bool pyfree::createDir(std::string _dir)
{
	if(isExistDir(_dir))
		return true;
#ifdef WIN32
	int ret = _mkdir(_dir.c_str());
#else
	int ret = mkdir(_dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
#endif
	if (-1 == ret) {
#ifdef WIN32
		if (183 != GetLastError())
		{
			Print_WARN("create Directory %s is error,%d \r\n", _dir.c_str(), GetLastError());
			return false;
		}
#else
		if (EEXIST != errno) 
		{
			Print_WARN("create Directory %s is error, %s ! \r\n", _dir.c_str(), strerror(errno));
			return false;
		}else{
			Print_WARN("dir(%s) has exist,don't create it again!\n",_dir.c_str());
		}
#endif
	}
	return true;
};

bool pyfree::isExistDir(std::string _dir)
{
#ifdef WIN32
	if(!_access(_dir.c_str(),0))
	{
		return true;
	}
	else
	{
		Print_WARN("%s is not exist!\n",_dir.c_str());
		return false;
	}
#else
	DIR *dfd;
	if( (dfd = opendir(_dir.c_str())) == NULL )
	{
        return false;
	}else{
		return true;
	}
#endif // WIN32
}

bool pyfree::getCurrentDir(char* dir_, int len_)
{
	char* ret=NULL;
#ifdef WIN32
	ret =_getcwd(dir_, len_);
#else
	ret = getcwd(dir_, len_);
#endif // WIN32
	return (NULL!=ret);
}